/* eslint-disable @typescript-eslint/no-var-requires */
import { Button, Drawer, Form, FormInstance, Input, message, Modal, Popconfirm, Radio, Select, Table, Typography } from "antd";
import { ColumnProps } from "antd/lib/table";
import {
	Dispatch,
	FC,
	forwardRef,
	ForwardRefRenderFunction,
	MutableRefObject,
	SetStateAction,
	useCallback,
	useContext,
	useEffect,
	useImperativeHandle,
	useMemo,
	useRef,
	useState,
} from "react";
import {
	cancelPermissionAuth,
	createAndAuthPermission,
	createPermission,
	getRolePermissions,
	getSource,
	GetSourceParams,
	updatePermission,
} from "src/api";
import EllipsisText from "@/components/dataPresentation/EllipsisText";
import { Permission, PermissionRecord, RoleRecord } from "../RoleType";
import UnAuthPermissionTable, { UnAuthPermissionTableRef } from "./UnAuthPermissionTable";
import * as icons from "@ant-design/icons";
import { PageData } from "src/util";
import { debounce } from "lodash";
import { DefaultOptionType } from "antd/es/select";
import { AdminContext } from "src/layout/admin/admin";
const { Option } = Select;

interface PermissionDrawerProps {
	visible: boolean;
	setVisible: Dispatch<SetStateAction<boolean>>;
	operatedRole: MutableRefObject<RoleRecord | null>;
}
export interface PermissionFormFields {
	auth: boolean;
	name: string;
	url: string;
	method?: string;
	type: 1 | 2 | 3;
	icon: string | null;
	parentId: number | null;
}
export interface PermissionDrawerRef {
	showAddModal: () => void;
}
const PermissionDrawer: ForwardRefRenderFunction<PermissionDrawerRef, PermissionDrawerProps> = (
	{ visible, setVisible, operatedRole },
	ref
) => {
	useImperativeHandle(ref, () => ({
		showAddModal() {
			setModalVisible(true);
		},
	}));
	const pageRef = useRef(1);
	const pageSizeRef = useRef(10);
	const [permissionPageOptions, setPermissionPageOptions] = useState({
		current: pageRef.current,
		pageSize: pageSizeRef.current,
		total: 0,
	});
	const [permissionList, setPermissionList] = useState<PermissionRecord[]>([]);
	const fetchRolePermissions = async () => {
		const roleId = operatedRole.current?._id;
		if (!roleId) return message.error("角色id不存在");
		const res = await getRolePermissions({
			page: pageRef.current,
			pageSize: pageSizeRef.current,
			roleId,
		});
		setPermissionList(res.data?.data || []);
		setPermissionPageOptions({
			current: pageRef.current,
			pageSize: pageSizeRef.current,
			total: Number(res.data?.total) || 0,
		});
		return;
	};
	const unAuthTableRef = useRef<UnAuthPermissionTableRef>(null);
	const { fetchMenu, fetchMenuAndRoutes } = useContext(AdminContext);
	const permissionColumns = useMemo<ColumnProps<PermissionRecord>[]>(
		() => [
			{
				title: "权限名",
				dataIndex: "name",
				width: "220px",
				render(name) {
					return <EllipsisText>{name}</EllipsisText>;
				},
			},
			{
				title: "权限类型",
				width: "100px",
				dataIndex: "type",
				render(type: PermissionRecord["type"]) {
					return type === Permission.interface ? (
						<Typography.Text type="success">接口权限</Typography.Text>
					) : type === Permission.menu ? (
						<Typography.Text keyboard>菜单</Typography.Text>
					) : type === Permission.route ? (
						<Typography.Text keyboard>页面路由</Typography.Text>
					) : (
						"未知"
					);
				},
			},
			{
				title: "图标",
				dataIndex: "icon",
				width: "60px",
				render(icon: string) {
					// eslint-disable-next-line @typescript-eslint/no-var-requires
					const Icon = require("@ant-design/icons")[icon];
					if (!Icon) return "";
					return (
						<div className="text-center">
							<Icon />
						</div>
					);
				},
			},

			{
				title: "权限地址",
				dataIndex: "url",
				width: "250px",
				render(name) {
					return <EllipsisText>{name}</EllipsisText>;
				},
			},
			{
				title: "请求方法",
				dataIndex: "method",
				width: "100px",
			},
			{
				title: "父菜单",
				dataIndex: "parent",
				width: "120px",
				render(parent: PermissionRecord) {
					return <EllipsisText>{parent?.name}</EllipsisText>;
				},
			},
			{
				title: "操作",
				render(_, record) {
					return (
						<>
							<Button
								size="small"
								type="primary"
								onClick={() => {
									opPermissionType.current = "edit";
									operatedPermission.current = record;
									setSelectedType(record.type);
									setModalVisible(true);
									modalForm.current?.resetFields();
									setTimeout(() => modalForm.current?.setFieldsValue(record));
								}}
							>
								编辑
							</Button>
							<Popconfirm
								className="ml-2"
								title={`确定撤销【${record.name}】的授权吗？`}
								onConfirm={() => {
									if (!operatedRole.current?._id) return message.error("角色id不能为空");
									cancelPermissionAuth(record._id, operatedRole.current._id).then(async () => {
										await fetchRolePermissions();
										await unAuthTableRef.current?.fetchUnAuthPermissions();
										if (record.type === 2) {
											fetchMenu();
											fetchMenuAndRoutes();
										}
										message.success("已撤销");
									});
								}}
							>
								<Button size="small" danger>
									撤销
								</Button>
							</Popconfirm>
						</>
					);
				},
			},
		],
		[]
	);
	const [modalVisible, setModalVisible] = useState(false);
	const modalForm = useRef<FormInstance<PermissionFormFields>>(null);
	const [selectedType, setSelectedType] = useState<PermissionRecord["type"]>(1);
	const [iconList, setIconList] = useState<{ name: string; Icon: FC }[]>([]);
	const [parentMenuOptions, setparentMenuOptions] = useState<DefaultOptionType[]>([]);
	const opPermissionType = useRef<"add" | "edit">("add");
	const operatedPermission = useRef<PermissionRecord | null>(null);
	const searchParentMenus = useCallback(
		debounce(
			async (value?: string) => {
				const query: GetSourceParams = {
					source: "permission",
					type: 2,
					page: 1,
					pageSize: 9999,
				};
				if (value)
					query.name = {
						like: true,
						value: value.replaceAll("'", "").replaceAll('"', ""),
					};
				const { data } = await getSource<PageData<PermissionRecord[]>>(query);
				setparentMenuOptions(
					(data?.data || []).map((item) => {
						// eslint-disable-next-line @typescript-eslint/no-var-requires
						const Icon = item.icon ? require("@ant-design/icons")[item.icon] : "";
						return {
							label: (
								<div className="flex">
									<div className="inline-block" style={{ width: "17px" }}>
										{Icon ? <Icon /> : ""}
									</div>
									<span className="ml-2">{item.name}</span>
								</div>
							),
							value: item._id,
						};
					})
				);
			},
			300,
			{ leading: false, trailing: true }
		),
		[]
	);
	useEffect(() => {
		if (selectedType === 2) {
			searchParentMenus();
		}
	}, [selectedType]);
	useEffect(() => {
		if (visible) {
			pageRef.current = 1;
			pageSizeRef.current = 10;
			setPermissionPageOptions({
				current: 1,
				pageSize: 10,
				total: 0,
			});
			fetchRolePermissions();
		}
	}, [visible]);
	useEffect(() => {
		const list = Object.keys(icons)
			.filter((item) => item.endsWith("Outlined") || item.endsWith("Filled") || item.endsWith("TwoTone"))
			.map((item) => ({
				name: item,
				Icon: require("@ant-design/icons")[item],
			}));
		setIconList(list);
	}, []);
	return (
		<>
			<Drawer
				width={1200}
				closable
				open={visible}
				onClose={() => setVisible(false)}
				title={
					<div className="flex justify-end">
						<Button
							type="primary"
							onClick={() => {
								opPermissionType.current = "add";
								modalForm.current?.resetFields();
								setSelectedType(1);
								setModalVisible(true);
							}}
						>
							添加权限
						</Button>
					</div>
				}
			>
				<Table
					title={() => (
						<h1 className="text-center text-lg">
							<span className="font-bold">【{operatedRole.current?.name}】</span>
							已拥有的权限
						</h1>
					)}
					locale={{ emptyText: "暂无权限，可授予" }}
					pagination={{
						current: permissionPageOptions.current,
						pageSize: permissionPageOptions.pageSize,
						total: permissionPageOptions.total,
						onChange(page, pageSize) {
							pageRef.current = page;
							pageSizeRef.current = pageSize;
							setPermissionPageOptions({
								...permissionPageOptions,
								current: pageRef.current,
								pageSize: pageSizeRef.current,
							});
							fetchRolePermissions();
						},
					}}
					columns={permissionColumns}
					dataSource={permissionList.map((item, key) => ({
						...item,
						key,
					}))}
				/>
				<UnAuthPermissionTable
					handleEditPermission={(record) => {
						opPermissionType.current = "edit";
						operatedPermission.current = record;
						setSelectedType(record.type);
						setModalVisible(true);
						modalForm.current?.resetFields();
						setTimeout(() => modalForm.current?.setFieldsValue(record));
					}}
					ref={unAuthTableRef}
					visible={visible}
					fetchPromissions={fetchRolePermissions}
				/>
			</Drawer>
			<Modal
				title={opPermissionType.current === "add" ? "添加权限" : "编辑权限"}
				zIndex={1001}
				open={modalVisible}
				onCancel={() => setModalVisible(false)}
				forceRender
				onOk={() => {
					modalForm.current?.validateFields().then(async (formData) => {
						if (!operatedRole.current?._id) return;
						const { auth, ...remainingData } = formData;
						if (opPermissionType.current === "add") {
							if (auth) {
								await createAndAuthPermission({
									...remainingData,
									role_id: operatedRole.current._id,
								});
								await fetchRolePermissions();
							} else {
								await createPermission({
									...remainingData,
								});
								await unAuthTableRef.current?.fetchUnAuthPermissions();
							}
						}
						if (opPermissionType.current === "edit") {
							if (!operatedPermission.current) return message.error("权限id为空");
							await updatePermission({
								...remainingData,
								id: operatedPermission.current._id,
							});
							await fetchRolePermissions();
							await unAuthTableRef.current?.fetchUnAuthPermissions();
						}
						if (formData.type === 2) fetchMenu();
						message.success(opPermissionType.current === "add" ? "创建成功" : "编辑成功");
						setSelectedType(1);
						setModalVisible(false);
					});
				}}
			>
				<div className="mb-8"></div>
				<Form
					labelCol={{ span: 4 }}
					wrapperCol={{ span: 19 }}
					ref={modalForm}
					initialValues={{ type: 1, method: "GET", auth: true }}
				>
					<Form.Item label="权限名" name="name" rules={[{ required: true, message: "请输入权限名" }]}>
						<Input placeholder="请输入权限名" />
					</Form.Item>
					<Form.Item label="权限地址" name="url" rules={[{ required: true, message: "请输入权限地址" }]}>
						<Input placeholder="请输入权限地址" />
					</Form.Item>
					<Form.Item label="权限类型" name="type" rules={[{ required: true, message: "请选择权限类型" }]}>
						<Select
							onChange={(type) => {
								setSelectedType(type);
							}}
							placeholder="请选择权限类型"
						>
							<Option value={1}>权限</Option>
							<Option value={2}>菜单</Option>
							<Option value={3}>路由</Option>
						</Select>
					</Form.Item>
					{selectedType === 1 && (
						<Form.Item label="请求方法" name="method" rules={[{ required: true, message: "请选择请求方法" }]}>
							<Select placeholder="请选择请求方法">
								<Option value="GET">GET</Option>
								<Option value="POST">POST</Option>
								<Option value="PUT">PUT</Option>
								<Option value="PATCH">PATCH</Option>
								<Option value="OPTION">OPTION</Option>
								<Option value="DELETE">DELETE</Option>
							</Select>
						</Form.Item>
					)}
					{selectedType === 2 && (
						<Form.Item label="菜单图标" name="icon">
							<Select showSearch placeholder="请选择菜单图标">
								{iconList.map(({ Icon, name }, key) => (
									<Option key={key} value={name}>
										<Icon />
										<span className="ml-2">{name}</span>
									</Option>
								))}
							</Select>
						</Form.Item>
					)}
					{selectedType === 2 && (
						<Form.Item label="父菜单" name="parentId">
							<Select
								allowClear
								onSearch={searchParentMenus}
								filterOption={false}
								showSearch
								placeholder="请输入父菜单名"
								options={parentMenuOptions}
							/>
						</Form.Item>
					)}
					{opPermissionType.current === "add" && (
						<Form.Item name="auth" label="自动赋权">
							<Radio.Group>
								<Radio value={true}>是</Radio>
								<Radio value={false}>否</Radio>
							</Radio.Group>
						</Form.Item>
					)}
				</Form>
			</Modal>
		</>
	);
};

export default forwardRef(PermissionDrawer);
